Introducción a R para Ciencias Sociales

Sesión 02.1: Introducción a las estructuras de control

Javier Emmanuel Anguiano Pita

CONAHCYT-Universidad de Guadalajara

7 de enero de 2025

Agenda del día

  1. Introducción a las estructuras de control del código
    • Expresiones condicionales y bucles.
  2. Manipulación de datos con dplyr.
  3. Flujo de trabajo para el análisis de datos.

Estructuras de control

Introducción a la programación

Estructuras de control

  • Las estructuras de control establecen condicionales en nuestros programas. Por ejemplo, ¿qué condiciones deben cumplirse para realizar una operación? o ¿qué debe ocurrir para ejecutar una función?.

  • En otras palabras, determinan la lógica y el orden en el que ocurren las operaciones, en especial al definir funciones.

  • Las estructuras de control más usadas en R son las siguientes:

Estructura de control Descripción
if, else Sí, de otro modo
for Para cada uno en
while Mientras
break Interrupción
next Siguiente

Condicionales if y else

  • La función if (si) se usa cuando queremos que una operación se ejecute unicamente cuando se cumple una condición.

Ejemplo condicionales if y else

  • Para declarar un condicional si, iniciamos nuestra función con if():
if()
  • Dentro del paréntesis () insertamos la condición que queremos evaluar:
if(numero > 10)
  • Usamos {} para definir el código que queremos que se ejecute cuando se cumple la condición:
if(numero > 10){
  resultado <- "El número es mayor que 10"
}

Ejemplo condicionales if y else

  • Podemos usar la función else{} para establecer la acción a ejecutar si no se cumple la condición:
if(numero > 10){
  resultado <- "El número es mayor que 10"
} else {
  resultado <- "El número es menor que 10"
}
  • La identación es importante así como el uso correcto de {}.

  • Finalmente, si nos interesa que se muestre en la pantalla el resultado usamos la función print() o return().

  • Para usar nuestro condicionale debemos definir los argumentos de entrada (numero).

Ejemplo: condicionales if y else

numero <- 4

if(numero > 10){
  resultado <- "El número es mayor que 10"
} else {
  resultado <- "El número es menor que 10"
}
print(resultado)

Ejercicio

05:00
  • Escribe una función que tenga como argumento de entrada una edad (número) y su resultado nos muestre en la pantalla si se trata de un niño o un adulto. Usa los condicionales if y else.
    • Supon que la edad adulta se adquiere cuando la persona tiene una edad >= a 18 años.
probar_edad <- function(numero){
  if(numero >= 18){
    edad <- "adulto"
  } else{
    edad <- "niño"
  }
  return(edad)
}

numero <- 5
probar_edad(numero)
[1] "niño"

Uso de vectores en condicionales

  • Nota que el argumento de entrada solo es un número entero. ¿Qué sucede si tratamos de ejecutar el condicional sobre un vector?
numero <- c(5, 15, 21, 67, 40, 98)
probar_edad(numero)
  • En R podemos vectorizar el condicional usando la función ifelse().

  • En lugar de escribir una línea de código para cada comparación, podemos usar una sola llamada a esta función, que se aplicará a cada elemento de un vector.

  • Esta función tiene la siguiente estructura:

ifelse(vector_entrada, valor_SI_TRUE, valor_SI_FALSE)
  • En nuestro ejemplo sobre las edades:
numero <- c(5, 15, 21, 67, 40, 98)
ifelse( numero >= 18, "Adulto", "Niño")

Ejemplo: Función ifelse()

  • Podemos usar la función ifelse() para saber si los número en un vector son pares o nones:
num <- 1:10 

ifelse(num %% 2 == 0, "Par", "Non")
  • Esta función puede ser muy útil para recodificar datos:
num <- c(0, 1 , 1, 0 , 0 ,1, 0)
genero <- ifelse(num == 0, "Hombre", "Mujer")
genero

num2 <- c("Hombre", "Mujer", "Mujer", "Hombre")
genero2 <- ifelse(num2 == "Hombre", 0 , 1)
genero2

Bucles en R

  • En R, los bucles (loop) son estructuras de control de flujo que permiten repetir un bloque de código de forma cíclica ya sea un determinado número de veces o hasta que se cumpla una condición.

for

  • La estructura for nos permite ejecutar un bucle ( loop ) realizando una operación para cada elemento de un conjunto de datos.
  • Su estructura es la siguiente:
for(elementos in objeto){
  operacion_con_elemento
}
  • En lenguaje simple, le estamos diciendo a R:
    • PARA cada elemento EN un objeto, haz lo siguiente {}.
# Ejemplo del uso de un bucle "for"
dado <- 1:6
for(cara in dado){
  dado ^ 2
}

Uso de bucles for

  • Las operaciones en un bucle for se realizan pero sus resultados nunca son devueltos automáticamente, es necesario pedirlos de manera explícita.

  • Una solución para mostrar los resultados de un bucle for es usar la función print().

for(cara in dado) {
  print(cara ^ 2)
}
  • Comprobamos que la operación ha sido realizada a cada elemento de nuestro objeto. Sin embargo, usar print() sólo mostrará los resultados de las operaciones en la consola, no los asignará a un objeto.

Uso de índices en bucles

  • Si deseamos asignar los resultados de un bucle for a un objeto, usamos índices.
  • En R el primer elemento de un bucle siempre es identificado con el número 1, y se realizarán las operaciones hasta llegar al total de elementos que especifiquemos:
# Ejemplo de un dado de seis caras
dado <- 1:6

for(cara in dado){
  print(cara)
}
  • El nombre del índice lo podemos definir explícitamente. Normalmente, se denomina con la letra i.

Asignar valores en un bucle for

  • Para guardar los resultados de cada iteración de nuestro bucle for podemos generar un objeto vacío:
# Ejemplo de un dado de seis caras
dado <- 1:6
mi_vector <- NULL  # Objeto vacío 

for(cara in dado){
  mi_vector[cara] <- cara ^ 2
}

mi_vector

for y vectorización

  • Los resultados que obtuvimos usando el bucle for pueden obtenerse vectorizando la operación:
dado ^ 2 
  • En R el uso de bucles for son poco populares ya que es más rápido y sencillo vectorizar las operaciones.
  • Sin embargo, es conveniente que conozcamos esta estructura de control porque hay ocasiones en que es la mejor herramienta para realizar algunas tareas.

while

  • Este es un tipo de bucle que ocurre mientras una condición es verdadera (TRUE). La operación se realiza hasta que se llega a cumplir un criterio previamente establecido.

  • La sintaxis de whilees la siguiente:

while(condicion){
  operaciones
}
  • Con esto le decimos a R:
    • MIENTRAS esta condición es VERDADERA, haz estas operaciones.

Ejemplo de uso de while

Probemos sumar +1 a un valor, mientras que este sea menor que 5.

umbral <- 5
valor <- 0 

while(valor < umbral){
  print("Todavía no")
  valor <- valor + 1
}

Advertencia

¡Ten cuidado de crear bucles infinitos! Si ejecutas una condición que nunca será FALSE, este nunca se detendra.

  • Si haz ejecutado un bucle infinito presiona la tecla ESC para detener su ejecución. De otra forma, podría congelarse tu equipo.

break y next

  • En R las palabras break y next son palabras reservadas. Es decir, NO podemos asignarle nuevos valores y realizan una acción específica cuando aparecen en nuestro código.

  • break nos permite interrumpir un bucle.

  • next nos deja avanzar a la siguiente iteración saltándose la actual.

  • Ambas funciones pueden ser utilizadas en bucles de tipo for y while.

Ejemplo del uso de break

Interrumpimos un for cuando i es igual a 3, aunque aún queden 7 elementos en el objeto.

for(i in 1:10) {
  if(i == 3) {
    break
  }
  print(i)
}

Ejemplo del uso de break

  • Interrumpimos un while antes de se cumpla la condición de que numero sea mayor a 5, en cuanto este tiene el valor de 15.
numero <- 20

while(numero > 5) {
  if(numero == 15) {
    break
  }
  numero <- numero - 1
}
numero

Ejemplo del uso de next

Por su parte, usamos next para “saltarnos” una iteración en un bucle. Cuando la condición se cumple, esa iteración es omitida.

for(i in 1:4) {
  if(i == 3) {
    next
  }
  print(i)
}

Funciones apply

Funciones apply

  • La familia de funciones apply es usada para aplicar una función a cada elemento de una estructura de datos (i.e., matrices, dataframes, arrays y listas).

  • Con esta familia de funciones podemos automatizar tareas complejas usando pocas líneas de código.

  • En el paradigma de R, la familia de funciones apply reciben como argumentos un objeto y al menos una función.

  • En este curso trabajaremos únicamente con las funciones más generales y de uso común de esta familia:

    • apply()
    • lapply()

Función apply()

apply() aplica una función a todos los elementos de una matriz. - La estructura de esta función es la siguiente:

apply(X, MARGIN, FUN)
  • La función tiene tres argumentos:
    • X: Una matriz o un objeto que puede coercionarse como matriz (dataframe).
    • MARGIN: La dimensión (margen) que agrupará los elementos de la matriz X, para aplicar una función. 1 se refiere a las filas y 2 son columnas.
    • FUN: La función que queremos aplicar al objeto X en su dimensión MARGIN.

Ejemplo uso apply()

data("mtcars")  # Importamos datos de ejemplo
?mtcars
head(mtcars)
apply(mtcars,2,mean)  # Promedio por columna
apply(mtcars,2,max)  # Maximo por columna
apply(mtcars,2,min)  # Mínimo por columna

# Ejemplo de uso de matrices
m <- matrix(seq(1:16), nrow = 4, ncol = 4)
m

apply(m, 1, min)  # Mínimo por filas

Ejemplo uso apply()

También podemos definir funciones dentro de la función apply() y aplicarlas tanto por filas como por columnas:

# Ejemplo de uso de matrices
m <- matrix(seq(1:16), nrow = 4, ncol = 4)
m

# Cuadrado de cada valor x
apply(m, c(1,2), function(x){x^2})
  • Nota que apply() nos devuelve objetos del mismo tipo al que la función fue aplicada

Función lapply()

lapply() está diseñada para aplicar funciones a todos los elementos de una lista (por eso l).

  • Esta función intentará coercionar a una lista cualquier tipo de objeto que demos como argumento y después aplicará una función a todos sus elementos.
  • La estructura de esta función es la siguiente:
lapply(X, FUN)
  • En donde:
    • X es una lista u objeto coercionable a una lista.
    • FUN es la función a aplicar.
    • Nota que aquí no específicamos MARGIN porque las listas son estructuras unidimensionales que solo tienen largo.

Ejemplo uso lapply()

x <- 1: 5
raiz <- lapply(x, sqrt) # Nos devuelve una lista
raizdf <- unlist(lapply(x, sqrt)) # Convertimos en vector

# Contar caracteres en una palabra
ciudades_vec <- c("Aguascalientes", "Monterrey", "Guadalajara", "México")
ciudades_vec

contar_nchar <- lapply(ciudades_vec, nchar)
contar_nchar

Ejercicio con datos reales

  • Descarga el archivo en MS Excel PIBE_2020-2023.xlsx.
  • Importa la base de datos a R. Nota: usa la función read.csv().
  1. Usando la función apply() calcula el valor promedio del PIB de cada estado para el período 2020-2023. Guarda el resultado en una nueva variable denominada PIBE_promedio en el mismo dataframe.

  2. Usando la función lapply() calcula el valor aproximado del PIB nacional para cada año. Guarda el resultado en una nueva variable denominada PIB_Nacional. Nota: Supon que puedes aproximar el valor del PIB nacional sumando el valor de los PIBE’s.

Recapitular R base

Uso de corchetes y paréntesis

  • [ ]

    Indexar elementos en objetos.

  • ( )

    Pasar argumentos a funciones.

  • { }

    Definir acciones de condicionales, funciones, bucles, etc.

Ya entiendes el lenguaje de R

¿Qué tipo de datos conocemos?

  • numeric
  • character
  • factor
  • logical

¿Cómo podemos encontrar datos faltantes?

  • NA (No disponible)
  • NULL (No existe)
  • " " (Campo vacío)

Ya entiendes el lenguaje de R

¿Qué tipos de estructuras de datos existen?

  • vector (1-D)
  • dataframe (2-D)
  • list (M-D)

¿Qué funciones hemos usado?

  • c()
  • is.na()
  • mean()
  • apply()
  • if-statments
  • function
  • for/ while-loop

Obtener ayuda

  • Para obtener ayuda sobre una función podemos escribir en la consola: ?mean() o help("mean").
  • Usar un motor de busqueda en internet (i.e., Stackoverflow).
  • Modelos de IA generativa (LLM):
    • Ventajas: Puede escribir todo nuestro código a partir de una ide general.
    • Desventajas: no aprendemos. Puede alucinar.

Fin de la sesión